Sensor Fusion for Kinetis MCUs (ISSDK/KSDK version)
sensor_fusion.c
Go to the documentation of this file.
1 // Copyright (c) 2014, 2015, 2016, NXP Semiconductors N.V.,
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are met:
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above copyright
9 // notice, this list of conditions and the following disclaimer in the
10 // documentation and/or other materials provided with the distribution.
11 // * Neither the name of NXP Semiconductors N.V. nor the
12 // names of its contributors may be used to endorse or promote products
13 // derived from this software without specific prior written permission.
14 //
15 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 // DISCLAIMED. IN NO EVENT SHALL NXP SEMICONDUCTORS N.V. BE LIABLE FOR ANY
19 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 
26 /*! \file sensor_fusion.c
27  \brief The sensor_fusion.c file implements the top level programming interface
28 */
29 
30 /* Including needed modules to compile this module/procedure */
31 #include <stdio.h>
32 #include "sensor_fusion.h"
33 #include "magnetic.h"
34 #include "drivers.h"
35 #include "fxos8700_drv.h"
36 #include "status.h"
37 #include "control.h"
38 #include "fusion.h"
39 //#include "debug.h"
40 
41 /// Poor man's inheritance for status subsystem setStatus command
42 /// This function is normally involved via the "sfg." global pointer.
44 {
45  sfg->pStatusSubsystem->set(sfg->pStatusSubsystem, status);
46 }
47 
48 /// Poor man's inheritance for status subsystem queueStatus command.
49 /// This function is normally involved via the "sfg." global pointer.
51 {
52  sfg->pStatusSubsystem->queue(sfg->pStatusSubsystem, status);
53 }
54 
55 /// Poor man's inheritance for status subsystem updateStatus command.
56 /// This function is normally involved via the "sfg." global pointer.
58 {
60 }
61 
63 {
65 }
66 
67 /// utility function to insert default values in the top level structure
69  StatusSubsystem *pStatusSubsystem,
70  ControlSubsystem *pControlSubsystem)
71 {
72  sfg->iFlags = // all of the following defines are either 0x0000 or a 1-bit value (2, 4, 8 ...) and are defined in build.h
74  F_USING_MAG |
75  F_USING_GYRO |
78  F_ALL_SENSORS | // refers to all applicable sensor types for the given physical unit
79  F_1DOF_P_BASIC | // 1DOF pressure (altitude) and temperature: (pressure)
80  F_3DOF_G_BASIC | // 3DOF accel tilt: (accel)
81  F_3DOF_B_BASIC | // 3DOF mag eCompass (vehicle): (mag)
82  F_3DOF_Y_BASIC | // 3DOF gyro integration: (gyro)
83  F_6DOF_GB_BASIC | // 6DOF accel and mag eCompass)
84  F_6DOF_GY_KALMAN | // 6DOF accel and gyro (Kalman): (accel + gyro)
85  F_9DOF_GBY_KALMAN ; // 9DOF accel, mag and gyro (Kalman): (accel + mag + gyro)
86 
87  sfg->pControlSubsystem = pControlSubsystem;
88  sfg->pStatusSubsystem = pStatusSubsystem;
89  sfg->loopcounter = 0; // counter incrementing each iteration of sensor fusion (typically 25Hz)
90  sfg->systick_I2C = 0; // systick counter to benchmark I2C reads
91  sfg->systick_Spare = 0; // systick counter for counts spare waiting for timing interrupt
92  sfg->iPerturbation = 0; // no perturbation to be applied
93  sfg->installSensor = installSensor; // function for installing a new sensor into the structures
94  sfg->initializeFusionEngine = initializeFusionEngine; // function for installing a new sensor into the structures
95  sfg->readSensors = readSensors; // function for installing a new sensor into the structures
96  sfg->runFusion = runFusion; // function for installing a new sensor into the structures
97  sfg->applyPerturbation = ApplyPerturbation; // function used for step function testing
98  sfg->conditionSensorReadings = conditionSensorReadings; // function does averaging, HAL adjustments, etc.
99  sfg->clearFIFOs = clearFIFOs; // function to clear FIFO flags sfg->applyPerturbation = ApplyPerturbation; // function used for step function testing
100  sfg->setStatus = setStatus; // function to immediately set status change
101  sfg->queueStatus = queueStatus; // function to queue status change
102  sfg->updateStatus = updateStatus; // function to promote queued status change
103  sfg->testStatus = testStatus; // function for unit testing the status subsystem
104  sfg->pSensors = NULL; // pointer to linked list of physical sensors
105 // put error value into whoAmI as initial value
106 #if F_USING_ACCEL
107  sfg->Accel.iWhoAmI = 0;
108 #endif
109 #if F_USING_MAG
110  sfg->Mag.iWhoAmI = 0;
111 #endif
112 #if F_USING_GYRO
113  sfg->Gyro.iWhoAmI = 0;
114 #endif
115 #if F_USING_PRESSURE
116  sfg->Pressure.iWhoAmI = 0;
117 #endif
118 }
119 /// installSensor is used to instantiate a physical sensor driver into the
120 /// sensor fusion system.
121 /// This function is normally involved via the "sfg." global pointer.
123  SensorFusionGlobals *sfg, ///< top level fusion structure
124  PhysicalSensor *pSensor, ///< pointer to structure describing physical sensor
125  uint16_t addr, ///< I2C address for sensor (if applicable)
126  uint16_t schedule, ///< Parameter to control sensor sampling rate
127  void *bus_driver, ///< ISSDK sensor bus driver (usually KSDK I2C bus)
128  initializeSensor_t *initialize, ///< pointer to sensor initialization function
129  readSensor_t *read) ///< pointer to sensor read function
130 {
131  if (sfg && pSensor && bus_driver && initialize && read)
132  {
133  pSensor->bus_driver = bus_driver;
134  pSensor->initialize = initialize; // The initialization function is responsible for putting the sensor
135  // into the proper mode for sensor fusion. It is normally KSDK-based.
136  pSensor->read = read; // The read function is responsible for taking sensor readings and
137  // loading them into the sensor fusion input structures. Also KDSK-based.
138  pSensor->addr = addr; // I2C address if applicable
139  pSensor->schedule = schedule;
140  pSensor->slaveParams.pReadPreprocessFN = NULL; // SPI-specific parameters get overwritten later if used
141  pSensor->slaveParams.pWritePreprocessFN = NULL;
142  pSensor->slaveParams.pTargetSlavePinID = NULL;
143  pSensor->slaveParams.spiCmdLen = 0;
144  pSensor->slaveParams.ssActiveValue = 0;
145  // Now add the new sensor at the head of the linked list
146  pSensor->next = sfg->pSensors;
147  sfg->pSensors = pSensor;
148  return (0);
149  }
150  else
151  {
152  return (1);
153  }
154 }
155 // The initializeSensors function traverses the linked list of physical sensor
156 // types and calls the initialization function for each one.
158 {
159  PhysicalSensor *pSensor;
160  int8_t s;
161  int8_t status = 0;
162  for (pSensor = sfg->pSensors; pSensor != NULL; pSensor = pSensor->next)
163  {
164  s = pSensor->initialize(pSensor, sfg);
165  if (status == 0) status = s; // will return 1st error flag, but try all sensors
166  }
167  return (status);
168 }
169 
170 // process<Sensor>Data routines do post processing for HAL and averaging. They
171 // are called from the readSensors() function below.
172 #if F_USING_ACCEL
173 void processAccelData(SensorFusionGlobals *sfg)
174 {
175  int32 iSum[3]; // channel sums
176  int16 i, j; // counters
177  if (sfg->Accel.iFIFOExceeded > 0) {
178  sfg->setStatus(sfg, SOFT_FAULT);
179  }
180 
181  ApplyAccelHAL(&(sfg->Accel)); // This function is board-dependent
182 
183  // calculate the average HAL-corrected measurement
184  for (j = CHX; j <= CHZ; j++) iSum[j] = 0;
185  for (i = 0; i < sfg->Accel.iFIFOCount; i++)
186  for (j = CHX; j <= CHZ; j++) iSum[j] += sfg->Accel.iGsFIFO[i][j];
187  if (sfg->Accel.iFIFOCount > 0)
188  {
189  for (j = CHX; j <= CHZ; j++)
190  {
191  sfg->Accel.iGs[j] = (int16)(iSum[j] / (int32) sfg->Accel.iFIFOCount);
192  sfg->Accel.fGs[j] = (float)sfg->Accel.iGs[j] * sfg->Accel.fgPerCount;
193  }
194  }
195 
196  // apply precision accelerometer calibration (offset V, inverse gain invW and rotation correction R^T)
197  // to map fGs onto fGc (g), iGc (counts)
198  fInvertAccelCal(&(sfg->Accel), &(sfg->AccelCal));
199 
200  // update the precision accelerometer data buffer
201  fUpdateAccelBuffer(&(sfg->AccelCal),
202  &(sfg->AccelBuffer),
203  &(sfg->Accel),
205  return;
206 }
207 #endif
208 #if F_USING_MAG
210 {
211  int32 iSum[3]; // channel sums
212  int16 i, j; // counters
213 
214  // printf("ProcessingMagData()\n");
215  if (sfg->Mag.iFIFOExceeded > 0) {
216  sfg->setStatus(sfg, SOFT_FAULT);
217  }
218 
219  ApplyMagHAL(&(sfg->Mag)); // This function is board-dependent
220 
221  // calculate the average HAL-corrected measurement
222  for (j = CHX; j <= CHZ; j++) iSum[j] = 0;
223  for (i = 0; i < sfg->Mag.iFIFOCount; i++)
224  for (j = CHX; j <= CHZ; j++) iSum[j] += sfg->Mag.iBsFIFO[i][j];
225  if (sfg->Mag.iFIFOCount > 0)
226  {
227  for (j = CHX; j <= CHZ; j++)
228  {
229  sfg->Mag.iBs[j] = (int16)(iSum[j] / (int32) sfg->Mag.iFIFOCount);
230  sfg->Mag.fBs[j] = (float)sfg->Mag.iBs[j] * sfg->Mag.fuTPerCount;
231  }
232  }
233 
234  // remove hard and soft iron terms from fBs (uT) to get calibrated data fBc (uT), iBc (counts) and
235  // update magnetic buffer avoiding a write while a magnetic calibration is in progress.
236  // run one iteration of the time sliced magnetic calibration
237  fInvertMagCal(&(sfg->Mag), &(sfg->MagCal));
238  if (!sfg->MagCal.iMagBufferReadOnly)
239  iUpdateMagBuffer(&(sfg->MagBuffer), &(sfg->Mag), sfg->loopcounter);
240  fRunMagCalibration(&(sfg->MagCal), &(sfg->MagBuffer), &(sfg->Mag),
241  sfg->loopcounter);
242 
243  return;
244 }
245 #endif
246 #if F_USING_GYRO
247 void processGyroData(SensorFusionGlobals *sfg)
248 {
249  int32 iSum[3]; // channel sums
250  int16 i, j; // counters
251  if (sfg->Gyro.iFIFOExceeded > 0) {
252  sfg->setStatus(sfg, SOFT_FAULT);
253  }
254 
255  ApplyGyroHAL(&(sfg->Gyro)); // This function is board-dependent
256 
257  // calculate the average HAL-corrected measurement
258  for (j = CHX; j <= CHZ; j++) iSum[j] = 0;
259  for (i = 0; i < sfg->Gyro.iFIFOCount; i++)
260  for (j = CHX; j <= CHZ; j++)
261  iSum[j] += sfg->Gyro.iYsFIFO[i][j];
262  if (sfg->Gyro.iFIFOCount > 0)
263  {
264  for (j = CHX; j <= CHZ; j++)
265  {
266  sfg->Gyro.iYs[j] = (int16)(iSum[j] / (int32) sfg->Gyro.iFIFOCount);
267  sfg->Gyro.fYs[j] = (float)sfg->Gyro.iYs[j] * sfg->Gyro.fDegPerSecPerCount;
268  }
269  }
270  return;
271 }
272 #endif
273 /// readSensors traverses the linked list of physical sensors, calling the
274 /// individual read functions one by one.
275 /// This function is normally involved via the "sfg." global pointer.
276 int8_t readSensors(
277  SensorFusionGlobals *sfg, ///< pointer to global sensor fusion data structure
278  uint16_t read_loop_counter ///< current loop counter (used for multirate processing)
279 )
280 {
281  PhysicalSensor *pSensor;
282  int8_t s;
283  int8_t status = 0;
284  float remainder;
285 
286  pSensor = sfg->pSensors;
287 
288  for (pSensor = sfg->pSensors; pSensor != NULL; pSensor = pSensor->next)
289  { if (pSensor->isInitialized) {
290  remainder = fmod(read_loop_counter, pSensor->schedule);
291  if (remainder==0) {
292  s = pSensor->read(pSensor, sfg);
293  if (status == 0) status = s; // will return 1st error flag, but try all sensors
294  }
295  }
296  }
297  if (status==SENSOR_ERROR_INIT) sfg->setStatus(sfg, HARD_FAULT); // Never returns
298  return (status);
299 }
300 /// conditionSensorReadings() transforms raw software FIFO readings into forms that
301 /// can be consumed by the sensor fusion engine. This include sample averaging
302 /// and (in the case of the gyro) integrations, applying hardware abstraction layers,
303 /// and calibration functions.
304 /// This function is normally involved via the "sfg." global pointer.
306 #if F_USING_ACCEL
307  if (sfg->Accel.isEnabled) processAccelData(sfg);
308 #endif
309 
310 #if F_USING_MAG
311  if (sfg->Mag.isEnabled) processMagData(sfg);
312 #endif
313 
314 #if F_USING_GYRO
315  if (sfg->Gyro.isEnabled) processGyroData(sfg);
316 #endif
317  return;
318 }
319 
320 void zeroArray(StatusSubsystem *pStatus, void* data, uint16_t size, uint16_t numElements, uint8_t check) {
321  uint16_t i;
322  uint8_t *d8;
323  uint16_t *d16;
324  uint32_t *d32;
325  switch(size) {
326  case 8:
327  d8 = data;
328  for (i=0; i<numElements; i++) d8[i]=0;
329  break;
330  case 16:
331  d16 = data;
332  for (i=0; i<numElements; i++) d16[i]=0;
333  break;
334  case 32:
335  d32 = data;
336  for (i=0; i<numElements; i++) d32[i]=0;
337  break;
338  default:
339  pStatus->set(pStatus, HARD_FAULT);
340  }
341  if (check) {
342  switch(size) {
343  case 8:
344  d8 = data;
345  for (i=0; i<numElements; i++)
346  if (d8[i]!=0) pStatus->set(pStatus, HARD_FAULT);
347  break;
348  case 16:
349  d16 = data;
350  for (i=0; i<numElements; i++)
351  if (d16[i]!=0) pStatus->set(pStatus, HARD_FAULT);
352  break;
353  case 32:
354  d32 = data;
355  for (i=0; i<numElements; i++)
356  if (d32[i]!=0) pStatus->set(pStatus, HARD_FAULT);
357  break;
358  }
359  return;
360  }
361 }
362 /// Function to clear FIFO at the end of each fusion computation
364  // We only clear FIFOs if the sensors are enabled. This allows us
365  // to continue to use these values when we've shut higher power consumption
366  // sensors down during periods of no activity.
367 #if F_USING_ACCEL
368  sfg->Accel.iFIFOCount=0;
369  sfg->Accel.iFIFOExceeded = false;
370 #endif
371 #if F_USING_MAG
372  sfg->Mag.iFIFOCount=0;
373  sfg->Mag.iFIFOExceeded = false;
374 #endif
375 #if F_USING_GYRO
376  sfg->Gyro.iFIFOCount=0;
377  sfg->Gyro.iFIFOExceeded = false;
378 #endif
379 }
380 
381 /// runFusion the top level call that actually runs the sensor fusion.
382 /// This is a utility function which manages the various defines in build.h.
383 /// You should feel free to drop down a level and implement only those portions
384 /// of fFuseSensors() that your application needs.
385 /// This function is normally involved via the "sfg." global pointer.
387 {
388  struct SV_1DOF_P_BASIC *pSV_1DOF_P_BASIC;
389  struct SV_3DOF_G_BASIC *pSV_3DOF_G_BASIC;
390  struct SV_3DOF_B_BASIC *pSV_3DOF_B_BASIC;
391  struct SV_3DOF_Y_BASIC *pSV_3DOF_Y_BASIC;
392  struct SV_6DOF_GB_BASIC *pSV_6DOF_GB_BASIC;
393  struct SV_6DOF_GY_KALMAN *pSV_6DOF_GY_KALMAN;
394  struct SV_9DOF_GBY_KALMAN *pSV_9DOF_GBY_KALMAN;
395  struct AccelSensor *pAccel;
396  struct MagSensor *pMag;
397  struct GyroSensor *pGyro;
398  struct PressureSensor *pPressure;
399  struct MagCalibration *pMagCal;
400 #if F_1DOF_P_BASIC
401  pSV_1DOF_P_BASIC = &(sfg->SV_1DOF_P_BASIC);
402 #else
403  pSV_1DOF_P_BASIC = NULL;
404 #endif
405 #if F_3DOF_G_BASIC
406  pSV_3DOF_G_BASIC = &(sfg->SV_3DOF_G_BASIC) ;
407 #else
408  pSV_3DOF_G_BASIC = NULL;
409 #endif
410 #if F_3DOF_B_BASIC
411  pSV_3DOF_B_BASIC = &(sfg->SV_3DOF_B_BASIC);
412 #else
413  pSV_3DOF_B_BASIC = NULL;
414 #endif
415 #if F_3DOF_Y_BASIC
416  pSV_3DOF_Y_BASIC = &(sfg->SV_3DOF_Y_BASIC);
417 #else
418  pSV_3DOF_Y_BASIC = NULL;
419 #endif
420 #if F_6DOF_GB_BASIC
421  pSV_6DOF_GB_BASIC = &(sfg->SV_6DOF_GB_BASIC);
422 #else
423  pSV_6DOF_GB_BASIC = NULL;
424 #endif
425 #if F_6DOF_GY_KALMAN
426  pSV_6DOF_GY_KALMAN = &(sfg->SV_6DOF_GY_KALMAN);
427 #else
428  pSV_6DOF_GY_KALMAN = NULL;
429 #endif
430 #if F_9DOF_GBY_KALMAN
431  pSV_9DOF_GBY_KALMAN = &(sfg->SV_9DOF_GBY_KALMAN);
432 #else
433  pSV_9DOF_GBY_KALMAN = NULL;
434 #endif
435 #if F_USING_ACCEL
436  pAccel = &(sfg->Accel);
437 #else
438  pAccel = NULL;
439 #endif
440 #if F_USING_MAG
441  pMag = &(sfg->Mag);
442  pMagCal = &(sfg->MagCal);
443 #else
444  pMag = NULL;
445  pMagCal = NULL;
446 #endif
447 #if F_USING_GYRO
448  pGyro = &(sfg->Gyro);
449 #else
450  pGyro = NULL;
451 #endif
452 #if F_USING_PRESSURE
453  pPressure = &(sfg->Pressure);
454 #else
455  pPressure = NULL;
456 #endif
457 
458  // conditionSensorReadings(sfg); must be called prior to this function
459  // fuse the sensor data
460  fFuseSensors(pSV_1DOF_P_BASIC, pSV_3DOF_G_BASIC,
461  pSV_3DOF_B_BASIC, pSV_3DOF_Y_BASIC,
462  pSV_6DOF_GB_BASIC, pSV_6DOF_GY_KALMAN,
463  pSV_9DOF_GBY_KALMAN, pAccel, pMag, pGyro,
464  pPressure, pMagCal);
465  clearFIFOs(sfg);
466 }
467 
468 /// This function is responsible for initializing the system prior to starting
469 /// the main fusion loop.
470 /// This function is normally involved via the "sfg." global pointer.
472 {
473  int16_t status = 0;
474  ControlSubsystem *pComm;
475  pComm = sfg->pControlSubsystem;
476 
477  // configure the 24 bit downwards ARM systick timer and wait 50ms=CORE_SYSTICK_HZ / 20 clock ticks
478  // to avoid a race condition between Kinetis and the sensors after power on.
480  // wait 50ms to avoid a race condition with sensors at power on
481  ARM_systick_delay_ms(CORE_SYSTICK_HZ, 50);
482 
483  sfg->setStatus(sfg, INITIALIZING);
484  status = initializeSensors(sfg);
485  if (status!=SENSOR_ERROR_NONE) { // fault condition found
486  sfg->setStatus(sfg, HARD_FAULT); // Never returns
487  }
488 
489  // recall: typedef enum quaternion {Q3, Q3M, Q3G, Q6MA, Q6AG, Q9} quaternion_type;
490  // Set the default quaternion to the most sophisticated supported by this build
498 
499  // initialize the sensor fusion algorithms
500  fInitializeFusion(sfg);
501 
502  // reset the loop counter to zero for first iteration
503  sfg->loopcounter = 0;
504 
505  // initialize the magnetic calibration and magnetometer data buffer
506 #if F_USING_MAG
508 #endif
509 
510  // initialize the precision accelerometer calibration and accelerometer data buffer
511 #if F_USING_ACCEL
512  fInitializeAccelCalibration(&sfg->AccelCal, &sfg->AccelBuffer, &sfg->pControlSubsystem->AccelCalPacketOn );
513 #endif
514  sfg->setStatus(sfg, NORMAL);
515 
516  clearFIFOs(sfg);
517 }
518 
519 void conditionSample(int16_t sample[3])
520 {
521  // This function should be called for every 16 bit sample read from sensor hardware.
522  // It is responsible for making sure that we never pass on the value of -32768.
523  // That value cannot be properly negated using 16-bit twos complement math.
524  // The ability to be later negated is required for general compatibility
525  // with possible HAL (Hardware abstraction logic) which is run later in
526  // the processing pipeline.
527  if (sample[CHX] == -32768) sample[CHX]++;
528  if (sample[CHY] == -32768) sample[CHY]++;
529  if (sample[CHZ] == -32768) sample[CHZ]++;
530 }
531 void addToFifo(FifoSensor *sensor, uint16_t maxFifoSize, int16_t sample[3])
532 {
533  // Note that FifoSensor is a union of GyroSensor, MagSensor and AccelSensor.
534  // All contain FIFO structures in the same location. We use the Accel
535  // structure to index here.
536 
537  // example usage: if (status==SENSOR_ERROR_NONE) addToFifo((FifoSensor*) &(sfg->Mag), MAG_FIFO_SIZE, sample);
538  uint8_t fifoCount = sensor->Accel.iFIFOCount;
539  if (fifoCount < maxFifoSize) {
540  // we have room for the new sample
541  sensor->Accel.iGsFIFO[fifoCount][CHX] = sample[CHX];
542  sensor->Accel.iGsFIFO[fifoCount][CHY] = sample[CHY];
543  sensor->Accel.iGsFIFO[fifoCount][CHZ] = sample[CHZ];
544  sensor->Accel.iFIFOCount += 1;
545  sensor->Accel.iFIFOExceeded = 0;
546  } else {
547  //there is no room for a new sample
548  sensor->Accel.iFIFOExceeded += 1;
549  }
550 }
551 
void initSensorFusionGlobals(SensorFusionGlobals *sfg, StatusSubsystem *pStatusSubsystem, ControlSubsystem *pControlSubsystem)
utility function to insert default values in the top level structure
Definition: sensor_fusion.c:68
void ARM_systick_enable(void)
Initializing sensors and algorithms.
SV_3DOF_Y_BASIC structure is the 3DOF basic gyroscope state vector structure.
Quaternion derived from full 9-axis sensor fusion.
Definition: sensor_fusion.h:70
int16_t iGsFIFO[ACCEL_FIFO_SIZE][3]
FIFO measurements (counts)
void fInitializeFusion(SensorFusionGlobals *sfg)
Definition: fusion.c:51
ssUpdateStatus_t * test
unit test which simply increments to next state
Definition: status.h:53
#define F_USING_GYRO
nominally 0x0004 if a gyro is to be used, 0x0000 otherwise
#define CHY
Used to access Y-channel entries in various data data structures.
Definition: sensor_fusion.h:77
int8_t( readSensor_t)(struct PhysicalSensor *sensor, struct SensorFusionGlobals *sfg)
uint16_t iFIFOExceeded
Number of samples received in excess of software FIFO size.
int32_t loopcounter
counter incrementing each iteration of sensor fusion (typically 25Hz)
int16_t iBs[3]
averaged uncalibrated measurement (counts)
clearFIFOs_t * clearFIFOs
clear sensor FIFOs
int32_t systick_I2C
systick counter to benchmark I2C reads
void fInitializeMagCalibration(MagCalibration *pthisMagCal, MagBuffer *pthisMagBuffer)
Definition: magnetic.c:41
#define F_ALL_SENSORS
uint32_t iFlags
a bit-field of sensors and algorithms used
conditionSensorReadings_t * conditionSensorReadings
preprocessing step for sensor fusion
void setStatus(SensorFusionGlobals *sfg, fusion_status_t status)
Poor man&#39;s inheritance for status subsystem setStatus command This function is normally involved via ...
Definition: sensor_fusion.c:43
Lower level sensor fusion interface.
Quaternion derived from 3-axis mag only (auto compass algorithm)
Definition: sensor_fusion.h:66
MagCalibration MagCal
mag cal storage
#define F_USING_PRESSURE
nominally 0x0008 if altimeter is to be used, 0x0000 otherwise
void addToFifo(FifoSensor *sensor, uint16_t maxFifoSize, int16_t sample[3])
addToFifo is called from within sensor driver read functions
The top level fusion structure.
int8_t( initializeSensor_t)(struct PhysicalSensor *sensor, struct SensorFusionGlobals *sfg)
void zeroArray(StatusSubsystem *pStatus, void *data, uint16_t size, uint16_t numElements, uint8_t check)
volatile int8_t AccelCalPacketOn
variable used to coordinate accelerometer calibration
Definition: control.h:71
void iUpdateMagBuffer(MagBuffer *pthisMagBuffer, MagSensor *pthisMag, int32 loopcounter)
Definition: magnetic.c:103
installSensor_t * installSensor
function for installing a new sensor into t
void fInvertMagCal(MagSensor *pthisMag, MagCalibration *pthisMagCal)
Definition: magnetic.c:297
void * bus_driver
should be of type (ARM_DRIVER_I2C* for I2C-based sensors, ARM_DRIVER_SPI* for SPI) ...
void processMagData(SensorFusionGlobals *sfg)
StatusSubsystem() provides an object-like interface for communicating status to the user...
Definition: status.h:44
int8_t installSensor(SensorFusionGlobals *sfg, PhysicalSensor *pSensor, uint16_t addr, uint16_t schedule, void *bus_driver, initializeSensor_t *initialize, readSensor_t *read)
installSensor is used to instantiate a physical sensor driver into the sensor fusion system...
Quaternion derived from 3-axis gyro only (rotation)
Definition: sensor_fusion.h:67
void testStatus(SensorFusionGlobals *sfg)
Definition: sensor_fusion.c:62
Quaternion derived from 3-axis accel + 3 axis mag (eCompass)
Definition: sensor_fusion.h:68
This is the 3DOF basic accelerometer state vector structure.
int32_t int32
Definition: sensor_fusion.h:57
quaternion_type DefaultQuaternionPacketType
default quaternion transmitted at power on
Definition: control.h:65
void initializeFusionEngine(SensorFusionGlobals *sfg)
This function is responsible for initializing the system prior to starting the main fusion loop...
readSensor_t * read
pointer to function to read sensor using the supplied drivers
Quaternion derived from 3-axis accel + 3-axis gyro (gaming)
Definition: sensor_fusion.h:69
void fUpdateAccelBuffer(struct AccelCalibration *pthisAccelCal, struct AccelBuffer *pthisAccelBuffer, struct AccelSensor *pthisAccel, volatile int8 *AccelCalPacketOn)
Update the buffer used to store samples used for accelerometer calibration.
The AccelSensor structure stores raw and processed measurements for a 3-axis accelerometer.
void clearFIFOs(SensorFusionGlobals *sfg)
Function to clear FIFO at the end of each fusion computation.
readSensors_t * readSensors
read all physical sensors
struct ControlSubsystem * pControlSubsystem
Magnetic Calibration Structure.
Definition: magnetic.h:72
initializeFusionEngine_t * initializeFusionEngine
set sensor fusion structures to initial values
MagSensor Mag
magnetometer storage
The SV_1DOF_P_BASIC structure contains state information for a pressure sensor/altimeter.
This is the 3DOF basic magnetometer state vector structure/.
uint16_t schedule
Parameter to control sensor sampling rate.
Recoverable FAULT = something went wrong, but we can keep going.
#define F_1DOF_P_BASIC
1DOF pressure (altitude) and temperature algorithm selector - 0x0100 to include, 0x0000 otherwise ...
The FifoSensor union allows us to use common pointers for Accel, Mag & Gyro logical sensor structures...
#define F_9DOF_GBY_KALMAN
AccelSensor Accel
updateStatus_t * updateStatus
status=next status
The PressureSensor structure stores raw and processed measurements for an altimeter.
int8_t readSensors(SensorFusionGlobals *sfg, uint16_t read_loop_counter)
readSensors traverses the linked list of physical sensors, calling the individual read functions one ...
struct PhysicalSensor * next
pointer to next sensor in this linked list
int8_t iMagBufferReadOnly
flag to denote that the magnetic measurement buffer is temporarily read only
Definition: magnetic.h:100
float fuTPerCount
uT per count
initializeSensor_t * initialize
pointer to function to initialize sensor using the supplied drivers
bool isEnabled
true if the device is sampling
#define F_6DOF_GY_KALMAN
6DOF accel and gyro (Kalman) algorithm selector - 0x2000 to include, 0x0000 otherwise ...
SV_6DOF_GB_BASIC is the 6DOF basic accelerometer and magnetometer state vector structure.
void ApplyGyroHAL(GyroSensor *Gyro)
Apply the gyroscope Hardware Abstraction Layer.
The sensor_fusion.h file implements the top level programming interface.
void runFusion(SensorFusionGlobals *sfg)
runFusion the top level call that actually runs the sensor fusion. This is a utility function which m...
#define F_3DOF_G_BASIC
3DOF accel tilt (accel) algorithm selector - 0x0200 to include, 0x0000 otherwise
#define CHZ
void queueStatus(SensorFusionGlobals *sfg, fusion_status_t status)
Poor man&#39;s inheritance for status subsystem queueStatus command. This function is normally involved v...
Definition: sensor_fusion.c:50
void fRunMagCalibration(MagCalibration *pthisMagCal, MagBuffer *pthisMagBuffer, MagSensor *pthisMag, int32 loopcounter)
Definition: magnetic.c:325
Lower level magnetic calibration interface.
uint8_t iFIFOCount
number of measurements read from FIFO
Provides function prototypes for driver level interfaces.
he ControlSubsystem encapsulates command and data streaming functions.
Definition: control.h:64
#define F_USING_TEMPERATURE
nominally 0x0010 if temp sensor is to be used, 0x0000 otherwise
spiSlaveSpecificParams_t slaveParams
SPI specific parameters. Not used for I2C.
#define CHX
Used to access X-channel entries in various data data structures.
Definition: sensor_fusion.h:76
MagBuffer MagBuffer
mag cal constellation points
runFusion_t * runFusion
run the fusion routines
void conditionSample(int16_t sample[3])
conditionSample ensures that we never encounter the maximum negative two&#39;s complement value for a 16-...
struct StatusSubsystem * pStatusSubsystem
ssUpdateStatus_t * update
make pending status active/visible
Definition: status.h:52
Non-recoverable FAULT = something went very wrong.
Application-specific status subsystem.
An instance of PhysicalSensor structure type should be allocated for each physical sensors (combo dev...
uint8_t iFIFOCount
number of measurements read from FIFO
uint16_t iFIFOExceeded
Number of samples received in excess of software FIFO size.
uint16_t isInitialized
Bitfields to indicate sensor is active (use SensorBitFields from build.h)
void conditionSensorReadings(SensorFusionGlobals *sfg)
conditionSensorReadings() transforms raw software FIFO readings into forms that can be consumed by th...
float fBs[3]
averaged un-calibrated measurement (uT)
uint8_t iWhoAmI
sensor whoami
void updateStatus(SensorFusionGlobals *sfg)
Poor man&#39;s inheritance for status subsystem updateStatus command. This function is normally involved ...
Definition: sensor_fusion.c:57
Quaternion derived from 3-axis accel (tilt)
Definition: sensor_fusion.h:65
#define F_3DOF_Y_BASIC
3DOF gyro integration algorithm selector - 0x0800 to include, 0x0000 otherwise
void ApplyAccelHAL(AccelSensor *Accel)
Apply the accelerometer Hardware Abstraction Layer.
setStatus_t * queueStatus
queue status change for next regular interval
#define F_6DOF_GB_BASIC
6DOF accel and mag eCompass algorithm selector - 0x1000 to include, 0x0000 otherwise ...
Defines control sub-system.
int16_t iBsFIFO[MAG_FIFO_SIZE][3]
FIFO measurements (counts)
The MagSensor structure stores raw and processed measurements for a 3-axis magnetic sensor...
void fInvertAccelCal(struct AccelSensor *pthisAccel, struct AccelCalibration *pthisAccelCal)
function maps the accelerometer data fGs (g) onto precision calibrated and de-rotated data fGc (g)...
void fInitializeAccelCalibration(struct AccelCalibration *pthisAccelCal, struct AccelBuffer *pthisAccelBuffer, volatile int8 *AccelCalPacketOn)
Initialize the accelerometer calibration functions.
ssSetStatus_t * set
change status immediately - no delay
Definition: status.h:50
#define F_USING_ACCEL
nominally 0x0001 if an accelerometer is to be used, 0x0000 otherwise
fusion_status_t
Application-specific serial communications system.
void ARM_systick_delay_ms(uint32 iSystemCoreClock, uint32 delay_ms)
setStatus_t * setStatus
change status indicator immediately
int16_t int16
Definition: sensor_fusion.h:56
SensorFusionGlobals sfg
This is the primary sensor fusion data structure.
applyPerturbation_t * applyPerturbation
apply step function for testing purposes
Operation is Nominal.
void ApplyMagHAL(MagSensor *Mag)
Apply the magnetometer Hardware Abstraction Layer.
#define F_3DOF_B_BASIC
3DOF mag eCompass (vehicle/mag) algorithm selector - 0x0400 to include, 0x0000 otherwise ...
The GyroSensor structure stores raw and processed measurements for a 3-axis gyroscope.
uint16_t addr
I2C address if applicable.
#define F_USING_MAG
Definition: magnetic.h:38
volatile uint8_t iPerturbation
test perturbation to be applied
void fFuseSensors(struct SV_1DOF_P_BASIC *pthisSV_1DOF_P_BASIC, struct SV_3DOF_G_BASIC *pthisSV_3DOF_G_BASIC, struct SV_3DOF_B_BASIC *pthisSV_3DOF_B_BASIC, struct SV_3DOF_Y_BASIC *pthisSV_3DOF_Y_BASIC, struct SV_6DOF_GB_BASIC *pthisSV_6DOF_GB_BASIC, struct SV_6DOF_GY_KALMAN *pthisSV_6DOF_GY_KALMAN, struct SV_9DOF_GBY_KALMAN *pthisSV_9DOF_GBY_KALMAN, struct AccelSensor *pthisAccel, struct MagSensor *pthisMag, struct GyroSensor *pthisGyro, struct PressureSensor *pthisPressure, struct MagCalibration *pthisMagCal)
Definition: fusion.c:86
SV_6DOF_GY_KALMAN is the 6DOF Kalman filter accelerometer and gyroscope state vector structure...
applyPerturbation_t ApplyPerturbation
ApplyPerturbation is a reverse unit-step test function.
PhysicalSensor * pSensors
a linked list of physical sensors
int8_t initializeSensors(SensorFusionGlobals *sfg)
volatile quaternion_type QuaternionPacketType
quaternion type transmitted over UART
Definition: control.h:66
SV_9DOF_GBY_KALMAN is the 9DOF Kalman filter accelerometer, magnetometer and gyroscope state vector s...
ssSetStatus_t * queue
queue status change for next regular interval
Definition: status.h:51